package com.java.springcloud.util;

import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.StringRedisTemplate;

import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Slf4j
public class RedisTemplateUtils {

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    public boolean exists(String key) {
        return stringRedisTemplate.hasKey(key);
    }

    public boolean expire(String key, int expire) {
        return stringRedisTemplate.expire(key, expire, TimeUnit.SECONDS);
    }

    /**
     * 设置redis缓存
     */
    public boolean setNx(String key, String value, int expire) {
        try {
            return stringRedisTemplate.opsForValue().setIfAbsent(key, value, expire, TimeUnit.SECONDS);
        } catch (Exception e) {
            log.error("Redis set exception, key = " + key, e);
            return false;
        }
    }

    /**
     * 删除缓存
     *
     * @param key 可以传一个值 或多个
     */
    @SuppressWarnings("unchecked")
    public void del(String... key) {
        if (key != null && key.length > 0) {
            if (key.length == 1) {
                stringRedisTemplate.delete(key[0]);
            } else {
                stringRedisTemplate.delete(Arrays.stream(key).collect(Collectors.toList()));
            }
        }
    }

    /**
     * 设置redis缓存
     */
    public boolean set(String key, String value) {
        try {
            stringRedisTemplate.opsForValue().set(key, value);
            return true;
        } catch (Exception e) {
            log.error("Redis set exception, key = " + key, e);
            return false;
        }
    }

    /**
     * 设置redis缓存，并设置过期时间
     *
     * @param expire 过期时间 单位S
     */
    public boolean set(String key, String value, int expire) {
        try {
            if (expire < 1) {
                stringRedisTemplate.opsForValue().set(key, value);
            } else {
                stringRedisTemplate.opsForValue().set(key, value, expire, TimeUnit.SECONDS);
            }

            return true;
        } catch (Exception e) {
            log.error("Redis set exception, key = " + key, e);
            return false;
        }
    }

    /**
     * 获取redis缓存
     */
    public String get(String key) {
        try {
            return stringRedisTemplate.opsForValue().get(key);
        } catch (Exception e) {
            log.error("Redis get exception, key = " + key, e);
            return null;
        }
    }

    /**
     * 判断hash表中是否有该项的值
     *
     * @param key  键 不能为null
     * @param item 项 不能为null
     * @return true 存在 false不存在
     */
    public boolean hexists(String key, String item) {
        return stringRedisTemplate.opsForHash().hasKey(key, item);
    }

    public String hget(String key, String field) {
        HashOperations<String, String, String> stringOperation = stringRedisTemplate.opsForHash();
        return stringOperation.get(key, field);
    }

    public List<String> hmget(String key, String[] fields) {
        HashOperations<String, String, String> stringOperation = stringRedisTemplate.opsForHash();
        List<String> fieldList = Lists.newArrayList(fields);
        return stringOperation.multiGet(key, fieldList);
    }

    public Map<String, String> hmgetHash(String redisKey, List<String> fieldList) {
        Map<String, String> returnHash = new HashMap<>();
        returnHash.putAll(hmgetHashSub(redisKey, fieldList.toArray(new String[]{})));
        return returnHash;
    }


    private Map<String, String> hmgetHashSub(String redisKey, String[] fieldArray) {
        Map<String, String> returnHash = new HashMap<>();
        List<String> jsonList = hmget(redisKey, fieldArray);
        if (null == jsonList) {
            return returnHash;
        }
        int fieldIdx = 0;
        for (String s : jsonList) {
            returnHash.put(fieldArray[fieldIdx], s);
            fieldIdx++;
        }
        return returnHash;
    }

    public Map<String, String> hgetAll(String key) {
        HashOperations<String, String, String> stringOperation = stringRedisTemplate.opsForHash();
        return stringOperation.entries(key);
    }

    public void hmput(String key, Map<String, String> value, int expire) {
        HashOperations<String, String, String> stringOperation = stringRedisTemplate.opsForHash();
        stringOperation.putAll(key, value);
        stringRedisTemplate.expire(key, expire, TimeUnit.SECONDS);
    }

    public void hmput(String key, Map<String, String> value) {
        HashOperations<String, String, String> stringOperation = stringRedisTemplate.opsForHash();
        stringOperation.putAll(key, value);
    }

}
